package project.jsf;

import project.entity.Revisao;
import project.jsf.util.JsfUtil;
import project.jsf.util.PaginationHelper;
import project.ejbs.RevisaoFacade;

import java.io.Serializable;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.mail.MessagingException;
import project.ejbs.EmailFacade;
import project.ejbs.RevisorFacade;
import project.ejbs.Session;
import project.entity.Papel.Perfil;
import project.entity.Submissao;

@ManagedBean(name = "revisaoController")
@SessionScoped
public class RevisaoController implements Serializable {

    private Revisao current;
    private DataModel items = null;
    @EJB
    private Session sessao;
    @EJB
    private project.ejbs.RevisaoFacade ejbFacade;
    private PaginationHelper pagination;
    private int selectedItemIndex;
    @EJB
    private RevisorFacade ejbRevisorFacade;
    @EJB
    private EmailFacade ejbEmail;
    
    private Short[] classificacoes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    public RevisaoController() {
    }

    public Revisao getSelected() {
        if (current == null) {
            current = new Revisao();
            selectedItemIndex = -1;
        }
        return current;
    }

    private RevisaoFacade getFacade() {
        return ejbFacade;
    }

    public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {

                @Override
                public int getItemsCount() {
                    try {
                        if (sessao.getPapel().equals(Perfil.Revisor)){
                            return getFacade().countRevisor(sessao.getUsername());
                        } else {
                            return getFacade().countSubmissao(sessao.getIdSubmissao());
                        }
                    } catch (Exception e) {
                        return 0;
                    }
                }

                @Override
                public DataModel createPageDataModel() {
                    try {
                        if (sessao.getPapel().equals(Perfil.Revisor)){
                            return new ListDataModel(getFacade().searchRevisor(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}, sessao.getUsername()));
                        } else {
                            return new ListDataModel(getFacade().searchSubmissao(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}, sessao.getIdSubmissao()));
                        }
                    } catch (Exception e) {
                        return new ListDataModel();
                    }
                }
            };
        }
        return pagination;
    }

    public String prepareList() {
        recreateModel();
        return "List";
    }
    
    public String prepareRevisoesList(DataModel submissoes){
        sessao.setIdSubmissao(((Submissao)submissoes.getRowData()).getIdSubmissao());
        recreateModel();
        return "/revisao/List";
    }

    public String prepareView() {
        current = (Revisao) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "View";
    }

    public String prepareCreate() {
        current = new Revisao();
        selectedItemIndex = -1;
        return "Create";
    }

    public String prepareEdit() {
        current = (Revisao) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "Edit";
    }

    public String update(boolean finish) {
        try {
            String pagina;
            if (finish){
                pagina = "List";
                current.setEstado((short) 2);
                JsfUtil.addSuccessMessage("Revisao finalizada com sucesso");
                recreateModel();
            } else {
                pagina = "View";
                current.setEstado((short) 1);
                JsfUtil.addSuccessMessage("Revisao guardada com sucesso");
            }
            if (current.getCritica().length() > 10239){
                JsfUtil.addErrorMessage("Critica muito grande!");
                return null;
            }
            getFacade().edit(current);
            
            if( finish ){
                try {
                    ejbEmail.enviar(current.getSubmissao().getAutor().getEmail() , "Revisao da submissao concluida", "Caro/a " + current.getSubmissao().getAutor().getpNome() + " " + current.getSubmissao().getAutor().getuNome() + ",\nO seu artigo \"" + current.getSubmissao().getTitulo() + "\" ja foi revisto, e o resultado da revisao pode ser consuldado atraves do site.\n\nObrigado.");
                } catch (MessagingException ex) {
                    Logger.getLogger(RevisorController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
                
            
            return pagina;
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, "Ocurreu um erro ao tentar submeter a revisão");
            return null;
        }
    }

    public String destroy() {
        current = (Revisao) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        performDestroy();
        recreateModel();
        return "List";
    }

    public String destroyAndView() {
        performDestroy();
        recreateModel();
        updateCurrentItem();
        if (selectedItemIndex >= 0) {
            return "View";
        } else {
            // all items were removed - go back to list
            recreateModel();
            return "List";
        }
    }

    private void performDestroy() {
        try {
            getFacade().remove(current);
            JsfUtil.addSuccessMessage("Revisão eliminada com sucesso.");
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, "Ocurreu um erro ao tentar eliminar a revisão.");
        }
    }

    private void updateCurrentItem() {
        int count = getFacade().count();
        if (selectedItemIndex >= count) {
            // selected index cannot be bigger than number of items:
            selectedItemIndex = count - 1;
            // go to previous page if last page disappeared:
            if (pagination.getPageFirstItem() >= count) {
                pagination.previousPage();
            }
        }
        if (selectedItemIndex >= 0) {
            current = getFacade().findRange(new int[]{selectedItemIndex, selectedItemIndex + 1}).get(0);
        }
    }

    public DataModel getItems() {
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

    private void recreateModel() {
        items = null;
    }

    public String next() {
        getPagination().nextPage();
        recreateModel();
        return "List";
    }

    public String previous() {
        getPagination().previousPage();
        recreateModel();
        return "List";
    }
    
    public boolean isDono(String revisor){
        try{
            return sessao.getUsername().equals(revisor);
        } catch (Exception e){
            return false;
        }
    }

    public SelectItem[] getItemsAvailableSelectMany() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), false);
    }

    public SelectItem[] getItemsAvailableSelectOne() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), true);
    }
    
    public String getEstado(Revisao revisao){
        if (revisao.getSubmissao().getEvento().getDataFimRevisoes().before(new Date())){
            revisao.setEstado((short) -1);
            return "Anulada";
        }
        return (revisao.getEstado() == 0 ? "Nova" : (revisao.getEstado() == 1 ? "Guardada" : "Finalizada"));
    }

    public boolean editVerification(String revisor, short estado){
        return (isDono(revisor) && (estado == 0 || estado == 1));
    }
    
    /**
     * @return the classificacoes
     */
    public Short[] getClassificacoes() {
        return classificacoes;
    }

    @FacesConverter(forClass = Revisao.class)
    public static class RevisaoControllerConverter implements Converter {

        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            RevisaoController controller = (RevisaoController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "revisaoController");
            return controller.ejbFacade.find(getKey(value));
        }

        java.lang.String getKey(String value) {
            java.lang.String key;
            key = value;
            return key;
        }

        String getStringKey(java.lang.String value) {
            StringBuffer sb = new StringBuffer();
            sb.append(value);
            return sb.toString();
        }

        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof Revisao) {
                Revisao o = (Revisao) object;
                return getStringKey(o.getRevisor().getUsername());
            } else {
                throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + RevisaoController.class.getName());
            }
        }
    }
}
